#include <IRremote.h> 
 
#define RowA 4 
#define RowB 5
#define RowC 6
#define RowD 7
int hc138en=3; 
//no change
#define R1 11 
#define CLK 13 
#define STB 10 
#define DATAIN 12 
byte dots[] ={//bullet
  0x80,0x00,0x40,0x00,
  0x20,0x00,0x10,0x00,
  0x08,0x00,0x04,0x00,
  0x02,0x00,0x01,0x00,
  0x00,0x80,0x00,0x40,
  0x00,0x20,0x00,0x10,
  0x00,0x08,0x00,0x04,
  0x00,0x02,0x00,0x01
};
byte plane2[] ={
  0xE0,0x00,0x40,0x00,
  0x70,0x00,0x20,0x00,
  0x38,0x00,0x10,0x00,
  0x1C,0x00,0x08,0x00,
  0x0E,0x00,0x04,0x00,
  0x07,0x00,0x02,0x00,
  0x03,0x80,0x01,0x00,
  0x01,0xC0,0x00,0x80,
  0x00,0xE0,0x00,0x40,
  0x00,0x70,0x00,0x20,
  0x00,0x38,0x00,0x10,
  0x00,0x1C,0x00,0x08,
  0x00,0x0E,0x00,0x04,
  0x00,0x07,0x00,0x02
};
 
byte ece[]={ 
  0x00,0x00,0x1D,0xDC,
  0x04,0x44,0x1C,0x5C,
  0x04,0x44,0x1D,0xDC,
  0x00,0x00,0x00,0x00,
  0x1D,0xDC,0x11,0x50,
  0x11,0xDC,0x11,0x50,
  0x11,0xDC,0x00,0x00,
  0x00,0x00,0x00,0x00
};
 
 
 
//IR
const int irReceiverPin = 2; 
IRrecv irrecv(irReceiverPin); 
decode_results results;   
 
long IRright=0x00FF5AA5;    //right 6
long IRleft= 0x00FF10EF;     //left 4
long IRfire= 0x00FF18E7;         //fire 2
long IRreset=0x00FF6897;        //reset 0  
 
void spi_transfer(volatile char data){
  SPDR = data; 
  while (!(SPSR & (1<<SPIF))) {// Wait the end of the transmission
    ;
  }
}
//scan
void hc138sacn(byte r){ 
  digitalWrite(RowA,!(r & 0x01));
  digitalWrite(RowB,!(r & 0x02));
  digitalWrite(RowC,!(r & 0x04));
  digitalWrite(RowD,!(r & 0x08));
}
 int resetPin = 8;/////////
void setup () {
  digitalWrite(resetPin, HIGH);//////////////
  pinMode(RowA, OUTPUT);
  pinMode(RowB, OUTPUT);
  pinMode(RowC, OUTPUT);
  pinMode(RowD, OUTPUT); 
  pinMode(hc138en, OUTPUT);
  pinMode(R1, OUTPUT);
  pinMode(CLK, OUTPUT);
  pinMode(STB, OUTPUT); 
  pinMode(DATAIN, INPUT); 
  Serial.begin(19200);
  SPCR = (1<<SPE)|(1<<MSTR);
  delay(10);
  irrecv.enableIRIn();
}
 
byte row;
int count;
//bullet
byte rowb[6];
int time[6];  
int post[6];
int number;
int temp;
//base
int timec;
int numberc;
byte cave[34]={ // inital base
          0xE0,0x07,0xE0,0x07,
          0xE0,0x07,0xE0,0x07,
          0xE0,0x07,0xE0,0x07,
          0xE0,0x07,0xE0,0x07,
          0xE0,0x07,0xE0,0x07,
          0xE0,0x07,0xE0,0x07,
          0xE0,0x07,0xE0,0x07,
          0xE0,0x07,0xE0,0x07};
 
int fail=1;      
void loop () {
  if(fail==1){    
    for(int i=15;i>=0;i--) {
      spi_transfer(~(ece[i*2]));
      spi_transfer(~(ece[i*2+1]));
      digitalWrite(hc138en, 1); // close
      hc138sacn(15-i); 
      digitalWrite(STB, 0); 
      digitalWrite(STB, 1);
      delayMicroseconds(500) ; 
      digitalWrite(hc138en, 0); 
      delayMicroseconds(500) ; 
    }
    if (irrecv.decode(&results)) { 
      if (results.value ==IRreset ) //reset
      {   
        fail=0;
        count=8;
        byte rowb[6]={
          2,2,2,2,2,2        };
        int time[6]={
          0,0,0,0,0,0        };  
        int post[6]={
          0,0,0,0,0,0        };
        number=0;
        temp=0;
        timec=0;
        numberc=0;
       byte cave[34]={ // inital base
          0xE0,0x07,0xE0,0x07,
          0xE0,0x07,0xE0,0x07,
          0xE0,0x07,0xE0,0x07,
          0xE0,0x07,0xE0,0x07,
          0xE0,0x07,0xE0,0x07,
          0xE0,0x07,0xE0,0x07,
          0xE0,0x07,0xE0,0x07,
          0xE0,0x07,0xE0,0x07};
 
      }
      irrecv.resume();   
    }
  }
  else
  {
    int fire=0;
    if (irrecv.decode(&results))
    {         
      if (results.value ==IRright ) //right
      {        
        count=count-1;       
      }
      else if (results.value ==IRleft ) //left
      {        
        count=count+1;       
      }
      if (results.value ==IRfire ) //fire
      {        
        fire=1;              
      }
 
      if(count>14)
        count=14;
      if(count<1)
        count=1;
      irrecv.resume();    //continus
    }
    //plane
    for(row=1;row<3;row++)
    {
      if(row==1)   
      {
        spi_transfer(~(plane2[count*4-4])); 
        spi_transfer(~(plane2[count*4-3])); 
      }
      if(row==2)
      {
        spi_transfer(~(plane2[count*4-2])); 
        spi_transfer(~(plane2[count*4-1]));
      }             
 
      digitalWrite(hc138en, 1); 
      hc138sacn(row);
      digitalWrite(STB, 0); 
      digitalWrite(STB, 1);
      delayMicroseconds(350) ;
      digitalWrite(hc138en, 0);
      delayMicroseconds(350) ; 
    }
 
    //bullets
    if(fire==1)
    {
      number=temp;
      rowb[number]=3;  
      post[number]=count;
      temp=number+1;
      if(temp==6)
        temp=0;
    }
    for(int i=0;i<=5;i++)
    {
      if(rowb[i]>=3)
      {
        spi_transfer(~(dots[post[i]*2])); 
        spi_transfer(~(dots[post[i]*2+1]));
        time[i]++;
        digitalWrite(hc138en, 1);
        hc138sacn(rowb[i]); 
        digitalWrite(STB, 0);
        digitalWrite(STB, 1);
        delayMicroseconds(250) ; 
        digitalWrite(hc138en, 0); 
        delayMicroseconds(250) ;
 
        if(time[i]==30)
        {
          rowb[i]=rowb[i]+1;
          time[i]=0;
        }
        if(rowb[i]>15)
          rowb[i]=2;
      }
    }
    //base
    for(int i=0;i<=15;i++)
    {
      spi_transfer(~(cave[i*2]));
      spi_transfer(~(cave[i*2+1]));
 
      digitalWrite(hc138en, 1);
      hc138sacn(i); 
      digitalWrite(STB, 0); 
      digitalWrite(STB, 1);
      delayMicroseconds(100) ;
      digitalWrite(hc138en, 0); 
      delayMicroseconds(100) ;
 
      if(i==0) {
        timec=(timec+1)%100;
        if(numberc<200){
          cave[32]=(random(0,3)<<random(0,5)|0x80);
          cave[33]=(random(0,3)<<random(1,6)|0x01);
        }
        else if(numberc<500){
          cave[32]=(random(0,4)<<random(0,5)|0x80);
          cave[33]=(random(0,4)<<random(1,6)|0x01);
        } 
        else if(numberc<=900){
          cave[32]=(random(0,8)<<random(0,4)|0x80);
          cave[33]=(random(0,8)<<random(1,5)|0x01);
        } 
        else{
          numberc=900;
          cave[32]=(random(0,8)<<random(0,4)|0x80);
          cave[33]=(random(0,8)<<random(1,5)|0x01);
        }          
      }
 
      if(timec==0)
      {   
        cave[i*2]=cave[i*2+2];
        cave[i*2+1]=cave[i*2+3];
        numberc++;
      }
 
    }
 
    for(int j=0;j<=15;j++)
    {
      for(int k=0;k<=5;k++)
      {
        if(rowb[k]==j)
        {
          //bullet vs target  
          if((dots[post[k]*2]&cave[j*2])||(dots[post[k]*2+1]&cave[j*2+1]))
          {
            cave[j*2]=dots[post[k]*2]^cave[j*2];
            cave[j*2+1]=dots[post[k]*2+1]^cave[j*2+1];
            rowb[k]=2;
          }
        }     
      }
      //plane vs base   
      if(j==1)
        if((plane2[count*4-4]&cave[j*2])||(plane2[count*4-3]&cave[j*2+1]))
          fail=1;
      if(j==2)
        if((plane2[count*4-2]&cave[j*2])||(plane2[count*4-1]&cave[j*2+1]))     
          fail=1;
    }
  }
}

